#include "GLProgramMgr.h"
#include <iostream>

GLProgramMgr::GLProgramMgr() :
	runningProgram(0) {
}

GLuint GLProgramMgr::registerShaders(GLShader shader) {
	std::cout << "register shaders +" << std::endl;
	GLuint vertexShaderHandler = shader.getVertexShaderHandler();
	GLuint fragmentShaderHandler = shader.getFragmentShaderHandler();
	GLuint programHandler = glCreateProgram();
	if (programHandler == 0) {
		std::cout << "Error creating program object" << std::endl;
	} else {
		glAttachShader(programHandler, vertexShaderHandler);
		glAttachShader(programHandler, fragmentShaderHandler);

		std::map<std::string, int> attrs = shader.getInputAttributes();
		std::map<std::string, int>::iterator it;
		for (it = attrs.begin(); it != attrs.end(); it++) {
			glBindAttribLocation(programHandler, it->second, it->first.c_str());
		}
		attrs.clear();
	}
	std::cout << "register shaders -" << std::endl;
	return programHandler;
}

void linkProgram(GLuint programHandler) {
	GLint status;
	glGetProgramiv( programHandler, GL_LINK_STATUS, &status);
	if (status == GL_FALSE) {
		glLinkProgram( programHandler );
	}
}

void GLProgramMgr::runProgram(GLuint programHandler) {
	if (runningProgram == programHandler) {
		return;
	}

	std::cout << "use program + " << programHandler << std::endl;
	linkProgram(programHandler);
	std::cout << "program linked" << std::endl;
	GLint status;
	glGetProgramiv( programHandler, GL_LINK_STATUS, &status);
	if (status == GL_TRUE) {
		glUseProgram( programHandler );
		runningProgram = programHandler;
	} else {
		std::cout << "Failed to link shader program!\n" << std::endl;
		GLint logLen;
		glGetProgramiv( programHandler, GL_INFO_LOG_LENGTH, &logLen);
		if( logLen > 0 )
		{
			char * log = new char[logLen];
			GLsizei written;
			glGetProgramInfoLog(programHandler, logLen, &written, log);
			std::cout << "Program log: \n" << log << std::endl;
			delete [] log;
		}
	}
	std::cout << "use program -" << std::endl;
}
